package com.yuezhu.versionup;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;


/**
 * 下载任务队列
 *
 *
 */
public class TaskQueue {

	private Queue<DownloadInfo> queue;
	private int maxQueueSize = 10000;

	//储存对象和下载任务对应关系
	private Map<String,DownloadInfo> queueInfo;
	//储存已经开始的下载地址
	private Set<String> downUrls;
	//储存已经开始的下载任务
	private Set<String> taskIds;

	private static class ContextQueueHolder {
		private static TaskQueue instance = buildSingleton();

		private static TaskQueue buildSingleton() {
			return new TaskQueue();
		}
	}

	public static TaskQueue getInst() {
		return ContextQueueHolder.instance;
	}

	private TaskQueue() {
		this.queue = new LinkedBlockingQueue<DownloadInfo>(maxQueueSize);
		this.queueInfo = new HashMap<String,DownloadInfo>();
		this.downUrls = new HashSet<String>();
		this.taskIds = new HashSet<String>();
	}

	/**
	 * 添加下载队列
	 * @param message
	 */
	public void addMessage(DownloadInfo message) {
		String url = message.getDownUrl();
		String taskId = message.getTaskId();
		//先判断有没有此任务
		if(!taskIds.contains(taskId)){
			taskIds.add(taskId);
			downUrls.add(url);
			queue.offer(message);
			//queueInfo.put(message.getDownUrl(), message);
			queueInfo.put(message.getTaskId(), message);
		}
	}

	/**
	 * 获取队列
	 * @param timeoutInMillionSeconds
	 * @return
	 * @throws InterruptedException
	 */
	public DownloadInfo getMessage(int timeoutInMillionSeconds)
			throws InterruptedException {
		if (queue.isEmpty()) {
			Thread.sleep(timeoutInMillionSeconds);
		}
		if (queue.isEmpty()) {
			throw new InterruptedException("wait timeout");
		}
		DownloadInfo info = queue.poll();
		//queueInfo.remove(info.getDownUrl());
		//downUrls.remove(info.getDownUrl());
		queueInfo.remove(info.getTaskId());
		downUrls.remove(info.getDownUrl());
		taskIds.remove(info.getTaskId());
		return info;
	}

	/**
	 * 移除指定任务
	 * @param downUrl
	 */
	public void remove(String taskId){
		DownloadInfo info = queueInfo.get(taskId);
		if(null != info){
			if(queue.contains(info)){
				queue.remove(info);
				taskIds.remove(taskId);
				downUrls.remove(info.getDownUrl());
			}
		}
	}

	public int size() {
		return queue.size();
	}

	public void setMaxQueueSize(int maxQueueSize) {
		this.maxQueueSize = maxQueueSize;
	}

	public int getMaxQueueSize() {
		return maxQueueSize;
	}
}
